<template>
	<div class="map-content">
		<div v-if="!isDetail" class="flex items-center justify-between mb-4">
			<div class="search-container flex items-center">
				<input v-model="mapForm.keyword" class="flex-1" type="text" placeholder="搜地点" />
				<el-button type="primary" class="search-btn shrink-0" @click="mapSearchClick">
					<el-icon><Search /></el-icon>
				</el-button>

				<div v-show="showPoi" ref="poiRef" class="poi-container">
					<div v-for="poi in poiList" :key="poi.id" class="poi-item" @click="selectPoi(poi)">
						<div class="poi-name">{{ poi.name }}</div>

						<div class="poi-address">
							{{ poi.address }}
						</div>
					</div>
				</div>
			</div>
			<div class="radio-container flex items-center">
				<el-radio-group v-show="isStartDraw" v-model="mapForm.fenceType" class="flex items-center">
					<el-radio :value="0" size="large">打点</el-radio>
					<el-radio :value="1" size="large">圆形</el-radio>
					<el-radio :value="2" size="large">多边形</el-radio>
				</el-radio-group>
				<el-button v-show="!isStartDraw" class="opration-btn" type="primary" @click="startDraw"> 开始绘制 </el-button>

				<el-button v-show="isStartDraw" class="opration-btn del-btn mr-2" type="danger" @click="removeDraw">
					<el-icon><Delete /></el-icon>
				</el-button>

				<el-button v-show="isStartDraw" class="opration-btn" type="primary" @click="saveDraw"> 保存绘制 </el-button>
			</div>
		</div>
		<div :id="id" class="eletronic-fence" />
	</div>
</template>

<script setup lang="ts" name="ElectronicFence">
import { onClickOutside } from '@vueuse/core';
import { loadAmap } from '/@/utils/mapLoad';
import { searchPoi } from '/@/utils/mapUtils';

defineExpose({
	init,
	clearMap,
});

const emits = defineEmits(['draw-finish']);
const props = withDefaults(
	defineProps<{
		id?: string;
		fence?: VerticesType | string | null;
		isDetail?: boolean;
	}>(),
	{
		id: 'electronic-fence',
		fence: null,
		isDetail: false,
	}
);

let map: any;
let mouseTool: any;
let polygon: any;
let circle: any;
let marker: any;
type CircleType = {
	center: string[] | number[];
	radius: string | number;
};
export type VerticesType = {
	type: 0 | 1 | 2; // 0 点 1 圆 2 多边形
	data: CircleType | number[][];
};
const vertices: VerticesType = reactive({
	type: 0,
	data: [],
});
watch(
	() => props.fence,
	() => {
		// console.log("电子围栏", props.fence)
		drawCover();
	}
);

onUnmounted(() => {
	if (map) map.destroy();
});

async function init() {
	try {
		await loadAmap();
		map = new window.AMap.Map(props.id, {
			zoom: 14,
			center: [104.066392, 30.572921],
			scrollWheel: !props.isDetail,
		});
		// 鼠标绘画工具
		mouseTool = new window.AMap.MouseTool(map);
		// map.on('dblclick', () => {
		// 	console.log('触发地图鼠标左键双击事件');
		// 	if (isStartDraw.value) {
		// 		startDraw();
		// 	}
		// });
		mouseTool.on('draw', function (e: any) {
			if (mapForm.fenceType === 0) {
				const lat = e.obj.getPosition().lat;
				const lng = e.obj.getPosition().lng;

				vertices.type = 0;
				vertices.data = {
					center: [lng, lat],
					radius: '',
				};
			}
			if (mapForm.fenceType === 1) {
				const center = e.obj.getCenter().toArray();
				const radius = e.obj.getRadius();
				vertices.type = 1;

				vertices.data = {
					center,
					radius,
				};
			}
			if (mapForm.fenceType === 2) {
				const path = e.obj.getPath();

				vertices.type = 2;
				vertices.data = [];

				for (let i = 0; i < path.length; i++) {
					vertices.data.push([path[i].lng, path[i].lat]);
				}
			}

			if (mouseTool) mouseTool.close(false); //关闭，不清除覆盖物

			emits('draw-finish', {
				vertices: (vertices.data as number[][]).length ? vertices : '',
			});
		});

		// 绘制覆盖物
		drawCover();
	} catch (err) {
		console.error(err);
	}
}

// 绘制覆盖物
function drawCover() {
	if (!map) return;

	if (props.fence !== null && typeof props.fence !== 'string') {
		if (props.fence.type === 0) {
			const center = (props.fence.data as CircleType).center;
			addMarker(center[0], center[1]);
		}
		if (props.fence.type === 1) {
			drawCircle(props.fence.data as CircleType);
		}
		if (props.fence.type === 2) {
			drawPolygon(props.fence.data as number[][]);
		}
	} else {
		clearMap();
	}
}

function clearMap() {
	if (map) {
		map.clearMap();
	}
}

// 地图搜索
const mapForm = reactive({
	fenceType: 0,
	keyword: '',
});

watch(
	() => mapForm.fenceType,
	() => {
		removeDraw();
	},
	{
		immediate: true,
	}
);

// 搜索
const poiList = ref<any>([]);
const showPoi = ref(false);
const poiRef = shallowRef();
onClickOutside(poiRef, () => {
	showPoi.value = false;
});
async function mapSearchClick() {
	try {
		poiList.value = await searchPoi(mapForm.keyword);
		showPoi.value = true;
	} catch (err) {
		/* empty */
		showPoi.value = false;
		console.error(err);
	}
}
function selectPoi(poi: any) {
	const P = poi.location.lat;
	const R = poi.location.lng;

	map.panTo([R, P]);
	map.add(
		new window.AMap.Marker({
			position: [R, P],
		})
	);

	showPoi.value = false;
	poiList.value.length = 0;
	mapForm.keyword = '';
}

function initMouseTool() {
	// 点位
	if (mapForm.fenceType === 0) {
		if (mouseTool) mouseTool.marker();
	}

	// 圆形
	if (mapForm.fenceType === 1) {
		if (mouseTool)
			mouseTool.circle({
				fillColor: '#00b0ff',
				strokeColor: '#80d8ff',
			});
	}

	// 多边形
	if (mapForm.fenceType === 2) {
		if (mouseTool)
			mouseTool.polygon({
				fillColor: '#00b0ff',
				strokeColor: '#80d8ff',
			});
	}
}

// 按钮点击事件
const isStartDraw = ref(false);
function startDraw() {
	isStartDraw.value = true;
	// 每次开始绘制就清除上次的
	if (mouseTool) mouseTool.close(true); //关闭，清除覆盖物
	removeFence();

	initMouseTool();
}

// 保存绘制
function saveDraw() {
	if (mouseTool) mouseTool.close(false); //关闭，清除覆盖物
	nextTick(() => {
		isStartDraw.value = false;
		if (vertices.type === 0 || vertices.type === 1) {
			let data;
			if (Array.isArray(vertices.data)) {
				data = '';
			} else if ((vertices.data as CircleType).center.length) {
				data = vertices;
			} else {
				data = '';
			}

			emits('draw-finish', {
				vertices: data,
			});
		}

		if (vertices.type === 2) {
			emits('draw-finish', {
				vertices: (vertices.data as number[][]).length ? vertices : '',
			});
		}
	});
}

// 清除绘制
function removeDraw() {
	vertices.data = [];
	if (mouseTool) mouseTool.close(true); //关闭，清除覆盖物
	removeFence();
	initMouseTool();
}

// 移除覆盖物
function removeFence() {
	if (polygon) map.remove(polygon);
	if (circle) map.remove(circle);
	if (marker) map.remove(marker);

	emits('draw-finish', {
		vertices: '',
	});
}

// 添加坐标
function addMarker(R: number | string, P: number | string) {
	clearMarker();
	marker = new window.AMap.Marker({
		position: [R, P],
	});
	marker.setMap(map);
	map.setFitView([marker]);
}

//清空坐标
function clearMarker() {
	if (marker) {
		marker.setMap(null);
		marker = null;
	}
}

// 绘制图形
function drawPolygon(data: number[][]) {
	polygon = new window.AMap.Polygon({
		path: data,
		fillColor: '#ccebc5',
		strokeOpacity: 1,
		fillOpacity: 0.5,
		strokeColor: '#2b8cbe',
		strokeWeight: 1,
		strokeStyle: 'dashed',
		strokeDasharray: [5, 5],
	});

	map.add(polygon);

	map.setFitView([polygon]);
}

// 绘制圆形
function drawCircle(data: CircleType) {
	circle = new window.AMap.Circle({
		center: data.center,
		radius: data.radius, //半径
		borderWeight: 3,
		strokeColor: '#FF33FF',
		strokeOpacity: 1,
		strokeWeight: 6,
		fillOpacity: 0.4,
		strokeStyle: 'dashed',
		strokeDasharray: [10, 10],
		// 线样式还支持 'dashed'
		fillColor: '#1791fc',
		zIndex: 50,
	});

	map.add(circle);

	map.setFitView([circle]);
}
</script>

<style scoped lang="scss">
.map-content {
	position: relative;
	width: 100%;

	.eletronic-fence {
		width: 100%;
		height: 25.75rem;
	}

	.search-container {
		width: 400px;
		height: 40px;
		background: #ffffff;
		border-radius: 2px;
		border: 1px solid #d6d6d6;
		position: relative;

		input {
			padding: 5px 10px;
			border: none;
			height: 38px;
			border-radius: 4px;
			box-sizing: border-box;
			font-size: 12px;
		}

		.search-btn {
			width: 44px;
			height: 38px;
			border-radius: 2px;
			border: none;
			vertical-align: baseline;
		}
		.poi-container {
			position: absolute;
			top: 40px;
			left: 0px;
			width: 100%;
			height: 200px;
			background-color: #fff;
			overflow-y: auto;
			z-index: 2;
			box-shadow: 0 0 4px 4px rgba(0, 0, 0, 0.1);

			.poi-item {
				padding: 5px;
				border-bottom: 1px solid #f1f1f1;
				cursor: pointer;

				&:last-of-type {
					border-bottom: none;
				}
			}
			.poi-name {
				font-size: 14px;
			}
			.poi-address {
				font-size: 12px;
			}
		}
	}

	.radio-container {
		background-color: #fff;
		border-radius: 4px;

		.el-button + .el-button {
			margin-left: 0;
		}

		.el-radio {
			margin-right: 10px;
		}

		.opration-btn {
			width: 79px;
			height: 32px;
			border-radius: 2px;
		}

		.del-btn {
			background-color: var(--el-color-error);
			width: 38px;
		}
	}
}
</style>
